package com.example.demo.quartz.h3c;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import java.text.ParseException;
import java.util.List;
import java.util.function.Consumer;

/**
 * @author c10709
 * @Date 2018/9/29 17:27
 * @Description:
 */
@Configuration
public class QuartzSupport {

    private static final Logger logger = LoggerFactory.getLogger(QuartzSupport.class);
    @Autowired
    private Scheduler scheduler;

//    @Autowired
//    private ISysTimedTaskMapper sysTimedTaskMapper;
//
//    /**
//     * 初始化Quartz Job
//     */
//    public void initQuartzJob() {
//        List<SysTimedTask> tasks = sysTimedTaskMapper.selectList(
//                new QueryWrapper<SysTimedTask>().eq("is_start",true));
//        tasks.stream().forEach(taskSupplier);
//    }

    private Consumer<SysTimedTask> taskSupplier = quartz -> {
        try {
            // 启动调度器
            scheduler.start();
            //构建job信息
            JobDetail job = JobBuilder.newJob((Class<? extends Job>) Class.forName(quartz.getClassName()))
                    .withIdentity(quartz.getJobName(),quartz.getJobGroup())
                    .withDescription(quartz.getDescription()).build();
            // 触发时间点
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule( quartz.getCron());
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger"+quartz.getJobName(), quartz.getJobGroup())
                    .startNow().withSchedule(cronScheduleBuilder).build();
            //交由Scheduler安排触发
            scheduler.scheduleJob(job, trigger);
            logger.info("quartz job [" + quartz.getJobName() + "] start.");
        } catch (ClassNotFoundException e) {
            logger.error("Class Not found " + quartz.getClassName() + e);
        } catch (SchedulerException e) {
            logger.error(quartz.getJobName() + "quartz job error." + e);
        }
    };


    /**
     * 根据传入参数创建定时任务,如果任务已经则进行相应的修改
     * “*”字符代表所有可能的值因此，“*”在子表达式（月）里表示每个月的含义，“*”在子表达式（天（星期））表示星期的每一天
     * ? 表示不指定值
     * /”字符用来指定数值的增量例如：在子表达式（分钟）里的“0/15”表示从第0分钟开始，每15分钟 ;在子表达式（分钟）里的“3/20”表示从第3分钟开始，每20分钟（它和“3，23，43”）的含义一样
     * 秒 分 时 日 月 周 年
     * 例子：
     * 0/5 * * * * ? * 每隔5秒执行一次
     * 0 0 0/6 * * ? * 每天每隔6小时执行一次
     * 0 0 0/1 * * ? * 每天每隔1小时执行一次
     * 0 0/30 * * * ? * 每天每隔30分钟执行一次
     * 0 0/1 * * * ? * 每天每隔1分钟执行一次
     * @param quartzTaskDTO
     * @throws SchedulerException
     * @throws ParseException
     */
    public void createOrUpdateTask(QuartzTaskDTO quartzTaskDTO) throws SchedulerException {
        {
            TriggerKey triggerKey = TriggerKey.triggerKey(quartzTaskDTO.getJobName(), quartzTaskDTO.getJobGroup());
            CronTrigger trigger = (CronTrigger) scheduler
                    .getTrigger(triggerKey); // 不存在，创建一个
            if (null == trigger) {
                JobDetail jobDetail = JobBuilder
                        .newJob(quartzTaskDTO.getQuartzJob())
                        .withIdentity(quartzTaskDTO.getJobName(), quartzTaskDTO.getJobGroup())
                        .build();
                // jobDetail.getJobDataMap().put("scheduleJob", job);

                // 表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                        .cronSchedule(quartzTaskDTO.getCronExpression());
                //错过的任务不再执行
                scheduleBuilder.withMisfireHandlingInstructionDoNothing();
                // 按新的cronExpression表达式构建一个新的trigger
                trigger = TriggerBuilder.newTrigger()
                        .withIdentity(quartzTaskDTO.getJobName(), quartzTaskDTO.getJobGroup())
                        .withSchedule(scheduleBuilder).build();
                scheduler.scheduleJob(jobDetail, trigger);
            } else { // Trigger已存在，那么更新相应的定时设置 //表达式调度构建器
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
                        .cronSchedule(quartzTaskDTO.getCronExpression());
                //错过的任务不再执行
                scheduleBuilder.withMisfireHandlingInstructionDoNothing();
                // 按新的cronExpression表达式重新构建trigger
                trigger = trigger.getTriggerBuilder()
                        .withIdentity(triggerKey)
                        .withSchedule(scheduleBuilder).build();

                // 按新的trigger重新设置job执行
                scheduler.rescheduleJob(triggerKey, trigger);
            }
        }
    }

    /**
     * 关闭定时器
     *
     * @param jobKey
     * @throws SchedulerException
     */
    public void shutdown(JobKey jobKey) throws SchedulerException {
        //scheduler.pauseJob(jobKey);
        scheduler.deleteJob(jobKey);
    }

    /**
     * 删除定时器
     *
     * @param jobKey
     * @throws SchedulerException
     */
    public void delete(JobKey jobKey) throws SchedulerException {
        scheduler.deleteJob(jobKey);
    }

    // 执行一次
    @SuppressWarnings("all")
    public void executeForOnce(Class<? extends Job> clazz, String name) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey("for once", "once");// 随便定义
        scheduler.deleteJob(jobKey);// 目的是在每次执行前删除原来的，（之所以没有放在triggerJob后面是因为触发一次，马上删除，可能会导致没触发）。就算之前没有jobDetail，也不会报错
        JobDetail jobDetail = JobBuilder
                .newJob(clazz)
                .usingJobData("name",name)
                .withIdentity(jobKey.getName(), jobKey.getGroup()).storeDurably(true)
                .build();
        scheduler.addJob(jobDetail, true);
        scheduler.triggerJob(jobKey);	//没有delete，那么这个job会一直存在
    }

}
